import os
import wx

import wx.lib.filebrowsebutton as filebrowse
from LMG.GUI.taskbaricon import NOTIFY_SUPPORT
from LMG.GUI.Base.WidgetStack import WidgetStack
from LMG.GUI.Base.widgets import TitlePanel
from LMG.GUI.Base.dhmtimectrl import DHMTimeCtrl
from LMG.GUI.Base.hotkey import HotKeyTextCtrl
from LMG.Utility.helpers import getFontFromInfo, getInfoFromFont, makeNumCtrl
from BitTornado.natpunch import _upnp_supported, _natpmp_supported
#######################################################################################

class PreferencesDialog(wx.Frame):
    """
    The Preferences Dialog
    """

    def __init__(self, parent):
        """
        Default class constructor.
        """
        
        self.parent = parent
        style = wx.FRAME_TOOL_WINDOW | wx.DEFAULT_FRAME_STYLE | wx.FRAME_FLOAT_ON_PARENT
        style = style & ~(wx.RESIZE_BOX | wx.MAXIMIZE_BOX)
        wx.Frame.__init__(self, parent, -1, _('Preferences'), style = style)
    
        # Toolbar
        style = wx.TB_HORIZONTAL | wx.TB_FLAT | wx.CLIP_CHILDREN | wx.TB_TEXT 
        self._toolbar = wx.ToolBar(self, style = style)
        self._toolbar.SetToolBitmapSize(wx.Size(32, 32))
        self.SetToolBar(self._toolbar)

        # Panel
        self.outside = wx.BoxSizer()
        self.panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)

        # Book
        self._book = WidgetStack(self.panel)        
        sizer.Add(self._book, 1, wx.EXPAND|wx.ALL, 1)
                
        # Add the pages
        self.Initialise()

        # Add Buttons
        sizer.Add(wx.StaticLine(self.panel), 0, wx.GROW, 0)
        buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
        
        okButton = wx.Button(self.panel, wx.ID_OK, _("OK"))
        okButton.SetDefault()
        buttonsBox.Add(okButton, 0, wx.EXPAND|wx.ALL, 5)
       
        cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _("Cancel"))
        buttonsBox.Add(cancelButton, 0, wx.EXPAND|wx.ALL, 5)

        applyButton = wx.Button(self.panel, wx.ID_APPLY, _("Apply"))
        buttonsBox.Add(applyButton, 0, wx.EXPAND|wx.ALL, 5)
        
        sizer.Add(buttonsBox, 0, wx.ALIGN_RIGHT, 0)

        self.panel.SetSizer(sizer)
        self.outside.Add(self.panel, 1, wx.EXPAND, 0)
        self.SetSizer(self.outside)
        
        # Events Table
        self.Bind(wx.EVT_CLOSE, self.onCancel)
        self.Bind(wx.EVT_BUTTON, self.onOK, id = wx.ID_OK)
        self.Bind(wx.EVT_BUTTON, self.onCancel, id = wx.ID_CANCEL)
        self.Bind(wx.EVT_BUTTON, self.onApply, applyButton)
        # Accelerator Table
        self.Bind(wx.EVT_MENU, self.onCancel, id = wx.ID_CANCEL)
        self.SetAcceleratorTable(wx.AcceleratorTable([(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, wx.ID_CANCEL)]))

        # Show
        self.SetAutoLayout(True)
        
        if wx.Platform == "__WXMAC__":
            self.SetMinSize((380, self._toolbar.GetToolSize()[1] + 25))
        else:
            self.SetMinSize(self._toolbar.GetEffectiveMinSize() + wx.Size(10, 25))
            
        self.Fit()
        self.Centre(wx.HORIZONTAL)
        self.Show()
        
    def Initialise(self):
        """
        Initialzes the preferences pages.
        """
        def addPage(page, title, filename, selected = False):
            page = page(self._book)
            self._book.AddWidget(page)
            bmp = utility.makeBitmap('preferences', filename)
            item = self._toolbar.AddLabelTool(-1, title, bmp, kind = wx.ITEM_RADIO)
            self.map[item.GetId()] = page
            if selected:
                self.visited[page] = 1
            
        self.map = {}
        self.visited = {}

        addPage(GeneralPanel,    _("General"),      'prefGeneral.png', True)
        addPage(BandwidthPanel,  _("Bandwidth"),    'prefBandwidth.png')
        addPage(QueuePanel,      _("Queue"),        'prefTransfers.png')
        addPage(BitTorrentPanel, _("BitTorrent"),   'prefBitTorrent.png')
        addPage(NetworkPanel,    _("Network"),      'prefNetwork.png')
        addPage(DiskPanel,       _("Disk"),         'prefDisk.png')
        addPage(DisplayPanel,    _("Display"),      'prefDisplay.png')

        self._toolbar.Realize()
        
        self.Bind(wx.EVT_TOOL, self.onPageChanged)

    def onPageChanged(self, event):
        page = self.map[event.GetId()]
        page.SetFocus()
        self.visited[page] = 1
        self._book.RaiseWidget(page)
        self.Fit()
        #event.Skip()
        
    def onOK(self, event):
        self.onApply()
        self.onCancel()
        
    def onCancel(self, event = None):
        utility.frame.preferences = None
        self.Destroy()
        
    def onApply(self, event = None):
        for page in self.visited:
            page.apply()
            
        # write current changes to disk
        utility.config.Flush()
        
        utility.queue.changeABCParams()    #overwrite flag
        
            
#######################################################################################
        
class OptionPanel(wx.Panel):
    """
    Base class for option panels
    """
    
    def __init__(self, parent):
        """
        OptionPanel initialization
        """
        
        wx.Panel.__init__(self, parent, -1)
        
        self.changed = False
        
        self.outersizer = wx.BoxSizer(wx.VERTICAL)
        
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        
    def initTasks(self):
        """
        Things to do after the subclass has finished its init stage
        """
        
        self.loadValues()
        
        self.outersizer.Add(self.sizer, 1, wx.EXPAND)
        
        defaultsButton = wx.Button(self, -1, _('Revert to default'))
        wx.EVT_BUTTON(self, defaultsButton.GetId(), self.setDefaults)
        self.outersizer.Add(defaultsButton, 0, wx.ALIGN_RIGHT|wx.TOP|wx.BOTTOM, 5)

        self.SetSizerAndFit(self.outersizer)

    def loadValues(self, Read = None):
        """
        Dummy function that class members should override
        """ 
        pass

    def setDefaults(self, event = None):
        """
        Loads the default settings for that panel
        """        
        self.loadValues(utility.config.ReadDefault)
        
    def apply(self):
        """
        Dummy function that class members should override
        """
        pass
    
#######################################################################################
    
class GeneralPanel(OptionPanel):
    """
    General settings:
    - Language Selection
    - Hot Key
    - Closing confirmation
    - System Tray (MSW, GTK)
    - Torrent files association (MSW)
    """
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)

        sizer = self.sizer

        # Local interface
        ##################
        interfacesection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Local interface')), wx.VERTICAL)
        
        # Language Selection
        languageBox = wx.BoxSizer(wx.HORIZONTAL)        
        self.language_choice = wx.Choice(self, -1, choices = utility.lang.language_options.keys())
        languageBox.Add(wx.StaticText(self, wx.ID_STATIC, _("Choose Language:")), 0, wx.ALIGN_CENTER_VERTICAL)
        languageBox.Add(self.language_choice, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.EXPAND, 5)
        interfacesection.Add(languageBox, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        
        # Check for software updates
        self.checkforupdates = wx.CheckBox(self, -1, _('Check for updates automatically'))
        interfacesection.Add(self.checkforupdates, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # Confirm on close
        self.confirmonclose = wx.CheckBox(self, -1, _('Confirm on exit'))
        interfacesection.Add(self.confirmonclose, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(interfacesection, 0, wx.EXPAND|wx.ALL, 5)
   
        # System tray
        ##################
        if wx.Platform in ["__WXGTK__", "__WXMSW__"]:
            traysection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('System tray')), wx.VERTICAL)

            # Show in tray
            trayBox = wx.BoxSizer(wx.HORIZONTAL)        
            self.trayoptions = [_('Never'), _('On Minimize'), _('On Close'), _('Always')]
            self.mintray = wx.Choice(self, -1, choices = self.trayoptions)
            trayBox.Add(wx.StaticText(self, wx.ID_STATIC, _("Show in tray:")), 0, wx.ALIGN_CENTER_VERTICAL)
            trayBox.Add(self.mintray, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.EXPAND, 5)
            traysection.Add(trayBox, 0, wx.ALIGN_LEFT|wx.ALL, 5)

            # Single click to restore
            self.mintray_singleclick = wx.CheckBox(self, -1, _('Single click to restore window'))
            traysection.Add(self.mintray_singleclick, 0, wx.ALIGN_LEFT|wx.ALL, 5)

            sizer.Add(traysection, 0, wx.EXPAND|wx.ALL, 5)

        # Notifications
        ##################
        if NOTIFY_SUPPORT == 1:
            # Balloon Notifications
            self.mintray_balloontips = wx.CheckBox(self, -1, _('Show balloon notifications'))
            traysection.Add(self.mintray_balloontips, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        elif NOTIFY_SUPPORT == 2:
            # Growl Notifications
            self.mintray_balloontips = wx.CheckBox(self, -1, _('Show Growl notifications'))
            interfacesection.Add(self.mintray_balloontips, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # Other
        ##################
        othersection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Other')), wx.VERTICAL)
        if wx.Platform == "__WXMSW__":
            # Hot Key
            hotkeyBox = wx.BoxSizer(wx.HORIZONTAL)        
            self.hotkeycheck = wx.CheckBox(self, -1, _('Boss key:'))
            self.hotkeyctrl = HotKeyTextCtrl(self)
            hotkeyBox.Add(self.hotkeycheck, 0, wx.ALIGN_CENTER_VERTICAL)
            hotkeyBox.Add(self.hotkeyctrl, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.EXPAND, 5)
            othersection.Add(hotkeyBox, 0, wx.ALIGN_LEFT|wx.ALL, 5)

            # Associate with .torrent files
            self.associate = wx.CheckBox(self, -1, _('Make default BitTorrent client'))
            othersection.Add(self.associate, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        if wx.Platform == "__WXGTK__":
            filemanagerBox = wx.BoxSizer(wx.HORIZONTAL)
            self.filemanager = wx.ComboBox(self, -1, "", choices = utility.browsers, style = wx.CB_DROPDOWN)
            filemanagerBox.Add(wx.StaticText(self, wx.ID_STATIC, _("Open files with:")), 0, wx.ALIGN_CENTER_VERTICAL)
            filemanagerBox.Add(self.filemanager, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.EXPAND, 5)
            othersection.Add(filemanagerBox, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # Log to file
        self.logtofile = wx.CheckBox(self, -1, _('Log to file'))
        othersection.Add(self.logtofile, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        sizer.Add(othersection, 0, wx.EXPAND|wx.ALL, 5)

        self.initTasks()
        
    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read

        # Language Selection
        try:
            index = utility.lang.language_options.values().index(Read('lang', "int"))
            if (index > -1):
                self.language_choice.SetSelection(index)
        except Exception, e:
            print e
            
        # Check for updates
        #@TODO
        self.checkforupdates.SetValue(Read('checkforupdates', "boolean"))

        # Confirm on close
        self.confirmonclose.SetValue(Read('confirmonclose', "boolean"))

        if wx.Platform == "__WXGTK__":
            self.filemanager.SetValue(utility.browser)

        if wx.Platform in ["__WXGTK__", "__WXMSW__"]:
            # System Tray Settings
            mintray = Read('mintray', "int")
            if mintray >= len(self.trayoptions):
                mintray = len(self.trayoptions) - 1
            self.mintray.SetSelection(mintray)

            # Single click to restore
            #@TODO
            self.mintray_singleclick.SetValue(Read('mintray_singleclick', "boolean"))
            

        # Notifications
        if NOTIFY_SUPPORT:
            self.mintray_balloontips.SetValue(Read('mintray_balloontips', "boolean"))

        if wx.Platform == "__WXMSW__":
            # Boss Key
            self.hotkeycheck.SetValue(Read('hotkey', "boolean"))
            self.hotkeyctrl.modifiers = Read('hotkeymod', "int")
            self.hotkeyctrl.keys = Read('hotkeykeycode', "int")
            self.hotkeyctrl.wxkeys = Read('hotkeywxkeycode', "int")
            self.hotkeyctrl.Update()
            # Associate with .torrent files
            self.associate.SetValue(utility.regchecker.testRegistry())
            
        # Logger
        self.logtofile.SetValue(Read('filelogger', "boolean"))
        
    def apply(self):        
        # Language Selection
        langid = utility.lang.language_options.values()[self.language_choice.GetSelection()]
        utility.config.Write("lang", langid ,"int")
        utility.lang.update(langid)

        # Check for updates
        utility.config.Write('checkforupdates', self.checkforupdates.GetValue(), "boolean")

        # Confirm on close
        utility.config.Write('confirmonclose', self.confirmonclose.GetValue(), "boolean")

        if wx.Platform == "__WXGTK__":
            utility.browser = self.filemanager.GetValue()
            utility.config.Write('filemanager', utility.browser)

        if wx.Platform in ["__WXGTK__", "__WXMSW__"]:
            # System Tray Settings
            utility.config.Write('mintray', self.mintray.GetSelection(), "int")
            utility.frame.tbicon.updateIcon()
            # Single click to restore
            if utility.config.Write('mintray_singleclick', self.mintray_singleclick.GetValue(), "boolean"):
                if utility.frame.tbicon is not None:
                    utility.frame.tbicon.SetRestoreFromTaskbar()

        # Notifications
        if NOTIFY_SUPPORT:
            utility.config.Write('mintray_balloontips', self.mintray_balloontips.GetValue(), "boolean")

        if wx.Platform == "__WXMSW__":
            # Boss Key
            change = False
            if utility.config.Write('hotkeymod', self.hotkeyctrl.modifiers):
                change = True
            if utility.config.Write('hotkeykeycode', self.hotkeyctrl.keys):
                change = True
            if utility.hotkey["active"] != self.hotkeycheck.GetValue():
                change = True
            self.SetHotKey(change)
            utility.config.Write('hotkey', self.hotkeycheck.GetValue(), "boolean")
            utility.config.Write('hotkeywxkeycode', self.hotkeyctrl.wxkeys)
            # Associate with .torrent files
            utility.config.Write('associate', self.associate.GetValue(), "boolean")
            utility.regchecker.updateRegistry(self.associate.GetValue())

        # Logger
        if utility.config.Write('filelogger', self.logtofile.GetValue(), "boolean"):
            utility.window['log'].logger.enabledFileLogger(self.logtofile.GetValue())

        return True

    def SetHotKey(self, change):
        modifiers = self.hotkeyctrl.modifiers
        key = self.hotkeyctrl.keys
        wxkeycode = self.hotkeyctrl.wxkeys

        if modifiers is None or key is None:
            if utility.hotkey["active"]:
                if not utility.frame.UnregisterHotKey(utility.hotkey["ID"]):
                    utility.frame.Bind(wx.EVT_HOTKEY, lambda x: None, id = utility.hotkey["ID"])
                utility.hotkey["active"] = False
            self.hotkeycheck.SetValue(False)
        else:
            utility.hotkey["current"]["modifiers"] = modifiers
            utility.hotkey["current"]["keys"] = key
            utility.hotkey["current"]["wxkeycode"] = wxkeycode
       
        if self.hotkeycheck.GetValue():
            if change:
                utility.frame.RegisterHotKey(utility.hotkey["ID"], modifiers, key)
            utility.frame.Bind(wx.EVT_HOTKEY, utility.frame.HotKeyDown, id = utility.hotkey["ID"])
            utility.hotkey["active"] = True
        else:
            if not utility.frame.UnregisterHotKey(utility.hotkey["ID"]):
                utility.frame.Bind(wx.EVT_HOTKEY, lambda x: None, id = utility.hotkey["ID"])
            utility.hotkey["active"] = False

#######################################################################################

class DisplayPanel(OptionPanel):
    """
    Display options
    - List font
    - Progress bars
    """
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)

        sizer = self.sizer

        displaysection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Display Settings')), wx.VERTICAL)

        optionsTable = wx.GridSizer(0, 2, 5, 5)

        # List font
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('List font:')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.font = wx.FontPickerCtrl(self, style=wx.FNTP_USEFONT_FOR_LABEL)
        optionsTable.Add(self.font, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.EXPAND, 5)

        # Progress bars
        progressbarsBox = wx.BoxSizer(wx.HORIZONTAL)        
        self.progressbarsOptions = [_('None'), _('Generic'), _('Native')]
        self.progressbars = wx.Choice(self, -1, choices = self.progressbarsOptions)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _("Progress bars:")), 0, wx.ALIGN_CENTER_VERTICAL)
        optionsTable.Add(self.progressbars, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT|wx.EXPAND, 5)

        # Display interval
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Display interval:')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.display_interval = makeNumCtrl(self, 1, 2, 1, 0.5, 10.0)
        optionsTable.Add(self.display_interval, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)

        displaysection.Add(optionsTable, 0, wx.ALIGN_LEFT|wx.EXPAND|wx.ALL, 5)

        # Allow menu bitmaps
        self.allowmenubitmaps = wx.CheckBox(self, -1, "Show bitmaps in menus")
        displaysection.Add(self.allowmenubitmaps, 0, wx.ALL|wx.EXPAND, 5)

        sizer.Add(displaysection, 0, wx.ALL|wx.EXPAND, 5)


        self.initTasks()

    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read
            
        # List font                          
        self.font.SetSelectedFont(getFontFromInfo(Read('listfont', "bencode-fontinfo")))

        # Progress bars
        self.progressbars.SetSelection(min(Read('progress_bars', "int"), len(self.progressbarsOptions) - 1))

        # Display Interval
        self.display_interval.SetValue(max(Read('display_interval', "float"), 0.5))

        # Allow menu bitmaps
        self.allowmenubitmaps.SetValue(Read('allowmenubitmaps', "boolean"))
        
    def apply(self):
        # List font
        fontchanged = utility.config.Write('listfont', getInfoFromFont(self.font.GetSelectedFont()), "bencode-fontinfo")
        if fontchanged:
            for managedlist in utility.lists:
                try:
                    if utility.lists[managedlist]:
                        managedlist.loadFont()
                except:
                    pass

        # Progress bars
        if utility.config.Write('progress_bars', self.progressbars.GetSelection(), "int"):
            utility.window.list.ChangeProgressBarType()

        # Display Interval
        utility.config.Write('display_interval', max(self.display_interval.GetValue(), 0.5), "float")

        # Allow menu bitmaps
        if utility.config.Write('allowmenubitmaps', self.allowmenubitmaps.GetValue(), "boolean"):
            utility.frame.MenuBar.updateMenu()
            
        return True
    
#######################################################################################
class NetworkPanel(OptionPanel):
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)

        sizer = self.sizer

        # Port Settings
        ################
        portsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Port Settings')), wx.VERTICAL)

        # useport 
        portBox = wx.BoxSizer(wx.HORIZONTAL)
        portBox.Add(wx.StaticText(self, wx.ID_STATIC, _('Listening port: ')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.useport = makeNumCtrl(self, 1, min = 1, max = 65536)
        portBox.Add(self.useport, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
        portsection.Add(portBox, 0, wx.ALIGN_LEFT|wx.EXPAND|wx.LEFT, 5)
        portsection.Add((-1,3))

        # Randomize port on startup
        randPortBox = wx.BoxSizer(wx.HORIZONTAL)
        self.randomport = wx.CheckBox(self, -1, "Randomize port on startup")
        self.randomport.Bind(wx.EVT_CHECKBOX, self.OnRandomPortChange)
        self.minport = makeNumCtrl(self, 1, min = 1, max = 65536)
        self.maxport = makeNumCtrl(self, 1, min = 1, max = 65536)
        randPortBox.Add(self.randomport, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        randPortBox.Add(self.minport, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
        randPortBox.Add(wx.StaticText(self, wx.ID_STATIC, ' - '), 0, wx.ALIGN_CENTER_VERTICAL)
        randPortBox.Add(self.maxport, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
        portsection.Add(randPortBox, 0, wx.ALIGN_LEFT|wx.EXPAND|wx.LEFT, 5)

        # Tracker Settings
        ################
        trackersection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Internal Tracker')), wx.VERTICAL)
        self.tracker = wx.CheckBox(self, -1, _("Enable tracker"))
        self.trackerDir = wx.Button(self, -1, _("Open Directory"))
        self.trackerPage = wx.Button(self, -1, _("Open Page"))
        self.trackerUpdate = wx.Button(self, -1, _("Update"))
        self.Bind(wx.EVT_BUTTON, self.OnTrackerDir, self.trackerDir)
        self.Bind(wx.EVT_BUTTON, self.OnTrackerPage, self.trackerPage)
        self.Bind(wx.EVT_BUTTON, self.OnTrackerUpdate, self.trackerUpdate)
        self.trackerAddress = wx.TextCtrl(self, -1)

        trackerBox = wx.FlexGridSizer(cols = 2, vgap = 3, hgap = 12)
        trackerBox.Add(self.tracker, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        opentrackerBox = wx.BoxSizer(wx.HORIZONTAL)
        opentrackerBox.Add(self.trackerDir, 0, wx.ALIGN_CENTER_VERTICAL)
        opentrackerBox.Add(self.trackerPage, 0, wx.ALIGN_CENTER_VERTICAL)        
        opentrackerBox.Add(self.trackerUpdate, 0, wx.ALIGN_CENTER_VERTICAL)        
        trackerBox.Add(opentrackerBox)
        trackerBox.Add(wx.StaticText(self, wx.ID_STATIC, _('Tracker Address: ')), wx.ALIGN_CENTER_VERTICAL, 0)
        trackerBox.Add(self.trackerAddress, 1, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
        trackersection.Add(trackerBox, 0, wx.EXPAND|wx.LEFT, 5)
            
        # Advanced
        ################
        advancedsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Advanced Network Settings')), wx.VERTICAL)
        datasizer = wx.FlexGridSizer(cols = 2, vgap = 3, hgap = 12)

        # UPnP 
        datasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('UPnP :')), 1, wx.ALIGN_CENTER_VERTICAL)
        if _upnp_supported:
            self.upnp_choices = [_('Disabled'), _('Enabled (Fast)'), _('Enabled (Slow)'), _('Enabled (Direct)')]
        else:
            self.upnp_choices = [_('Disabled'), _('Enabled')]
        self.upnp = wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), self.upnp_choices)
        datasizer.Add(self.upnp, 0, wx.EXPAND, 0)

        # NAT-PMP
        if _natpmp_supported:
            datasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('NAT-PMP :')), 1, wx.ALIGN_CENTER_VERTICAL)
            natpmp_choices = [_('Disabled'), _('Enabled')]
            self.natpmp = wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), natpmp_choices)
            datasizer.Add(self.natpmp, 0, wx.EXPAND, 0)

        # Local IP
        self.ip_data = wx.TextCtrl(self, -1)
        datasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Local IP Address: ')), 1, wx.ALIGN_CENTER_VERTICAL)
        datasizer.Add(self.ip_data, 0, wx.EXPAND, 0)

        # IP to Bind to
        self.bind_data = wx.TextCtrl(self, -1)
        datasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('IP to bind to: ')), 1, wx.ALIGN_CENTER_VERTICAL)
        datasizer.Add(self.bind_data, 0, wx.EXPAND, 0)

        # Minimum Peers
        self.minpeers_data = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.minpeers_data.SetRange(10, 100)
        datasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Minimum number of peers: ')), 1, wx.ALIGN_CENTER_VERTICAL)
        datasizer.Add(self.minpeers_data)

        # Maximum Connections
        self.maxconnections_data = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.maxconnections_data.SetRange(20, 200)
        self.maxconnections = wx.CheckBox(self, -1, _('Maximum connections: '))
        self.Bind(wx.EVT_CHECKBOX, self.OnMaxConnections, self.maxconnections)
        datasizer.Add(self.maxconnections, 1, wx.ALIGN_CENTER_VERTICAL)
        datasizer.Add(self.maxconnections_data)

        advancedsection.Add(datasizer, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # Enable IPv6
        self.ipv6 = wx.CheckBox(self, -1, _("Initiate and receive connections via IPv6"))
        advancedsection.Add(self.ipv6, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # IPv6 binds IPv4
        self.ipv6bindsipv4 = wx.CheckBox(self, -1, _("IPv6 binds IPv4"))
        advancedsection.Add(self.ipv6bindsipv4, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        
        ####################################################################
        sizer.Add(portsection, 0, wx.EXPAND|wx.ALL, 5)
        sizer.Add(trackersection, 0, wx.EXPAND|wx.ALL, 5)
        sizer.Add(advancedsection, 0, wx.EXPAND|wx.ALL, 5)
        self.initTasks()

        self.OnRandomPortChange()
        self.OnMaxConnections()
        self.SetTrackerStatus()
        
    def OnRandomPortChange(self, event = None):
        enabled = self.randomport.GetValue()
        self.minport.Enable(enabled)
        self.maxport.Enable(enabled)
        
    def OnMaxConnections(self, event = None):
        self.maxconnections_data.Enable(self.maxconnections.GetValue())

    def SetTrackerStatus(self, event = None):
        self.trackerPage.Enable(utility.controller.tracker != None)
        self.trackerUpdate.Enable(utility.controller.tracker != None)

    def OnTrackerDir(self, event):
        directory = os.path.join(utility.configdir.dir_root, 'tracker')
        utility.open_new(directory)
        
    def OnTrackerPage(self, event):
        if utility.controller.tracker:
            wx.LaunchDefaultBrowser("http://localhost:%d" % utility.controller.listen_port) 

    def OnTrackerUpdate(self, event):
        if utility.controller.tracker:
            utility.controller.tracker.parse_allowed(add_task = False)
        
    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read

        # On Restore Defaults: Don't random new port
        useport = utility.config.Read('useport', 'int')
        self.useport.SetValue(useport)

        self.minport.SetValue(Read('minport', "int"))
        self.maxport.SetValue(Read('maxport', "int"))
        
        useportrange = Read('useportrange', 'boolean')
        self.randomport.SetValue(useportrange)
        
        # Local IP
        self.ip_data.SetValue(Read('ip'))
        
        # IP to Bind to
        self.bind_data.SetValue(Read('bind'))
        
        # Minimum Peers        
        self.minpeers_data.SetValue(Read('min_peers', "int"))
        
        # Maximum Connections
        maxconnections = Read('max_connections', "int")
        if maxconnections <= 0:
            maxconnections = 0
            self.maxconnections.SetValue(False)
        else:
            self.maxconnections.SetValue(True)
        self.maxconnections_data.SetValue(maxconnections)

        # Tracker
        self.tracker.SetValue(Read('tracker', "boolean"))
        self.trackerAddress.SetValue(Read('trackeraddress'))

        # IPv6
        self.ipv6.SetValue(Read('ipv6', "boolean"))
        self.ipv6bindsipv4.SetValue(Read('ipv6_binds_v4', "boolean"))

        # UPnP
        if _upnp_supported:
            upnp_val = Read('upnp_nat_access', "int")
            if upnp_val >= len(self.upnp_choices):
                upnp_val = len(self.upnp_choices) - 1
            self.upnp.SetStringSelection(self.upnp_choices[upnp_val])
        else:
            upnp_val = Read('upnp_nat_access', "int")
            if upnp_val == 0:
                self.upnp.SetStringSelection(self.upnp_choices[0])
            else:
                self.upnp.SetStringSelection(self.upnp_choices[1])

        # NAT-PNP
        if _natpmp_supported:
            natpmp_val = Read('natpmp', "int")
            self.natpmp.SetSelection(natpmp_val)
        
    def apply(self):
        
        # port
        utility.config.Write('useport', self.useport.GetValue())
        utility.config.Write('minport', self.minport.GetValue())
        utility.config.Write('maxport', self.maxport.GetValue())
        utility.config.Write('useportrange', self.randomport.GetValue(), "boolean")
        
        # Local IP
        utility.config.Write('ip', self.ip_data.GetValue())

        # IP to Bind to
        utility.config.Write('bind', self.bind_data.GetValue())
        
        # Minimum Peers
        minpeers = self.minpeers_data.GetValue()
        utility.config.Write('min_peers', minpeers)
        
        # Maximum Connections
        if self.maxconnections.GetValue():
            maxconnections = int(self.maxconnections_data.GetValue())
            maxinitiate = min(2 * minpeers, maxconnections)
        else:
            maxconnections = 0
            maxinitiate = 2 * minpeers
        utility.config.Write('max_initiate', maxinitiate)
        utility.config.Write('max_connections', maxconnections)

        # Tracker
        utility.config.Write('trackeraddress', self.trackerAddress.GetValue())
        enabletracker = self.tracker.GetValue()
        if utility.config.Write('tracker', enabletracker, "boolean"):
            if enabletracker:
                utility.controller.enableTracker()
            else:
                utility.controller.disableTracker()
            self.SetTrackerStatus()
            
        # IPv6
        utility.config.Write('ipv6', self.ipv6.GetValue(), "boolean")
        utility.config.Write('ipv6_binds_v4', self.ipv6bindsipv4.GetValue(), "boolean")

        # UPnP
        if _upnp_supported:
            utility.config.Write('upnp_nat_access', self.upnp.GetSelection())
        else:
            if self.upnp.GetSelection() == 0:
                utility.config.Write('upnp_nat_access', 0)
            else:
                utility.config.Write('upnp_nat_access', 3)

        # NAT-PNP
        if _natpmp_supported:
            utility.config.Write('natpmp', self.natpmp.GetSelection())
                                
################################################################
class QueuePanel(OptionPanel):
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)

        sizer = self.sizer

        # Activity 
        ############
        activitysection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Activity')), wx.VERTICAL)

        optionsTable = wx.FlexGridSizer(cols = 2, vgap = 3, hgap = 12)
        
        # Number of simultaneous active torrents
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Maximum number of active torrents:')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.numsimtext = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.numsimtext.SetRange(0, 1000)
        optionsTable.Add(self.numsimtext, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        
        # Consider torrents active if...
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Consider torrents active if they are:')), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.consideractiveOptions = [ _('Downloading') , _('Seeding'), _('Downloading or Seeding') ]
        self.consideractive  = wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), self.consideractiveOptions)
        optionsTable.Add(self.consideractive, 0, wx.ALIGN_CENTER_VERTICAL, 0)

        self.preferuncompleted = wx.CheckBox(self, -1, _('Prefer downloading tasks'))
        optionsTable.Add(self.preferuncompleted, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)

        activitysection.Add(optionsTable, 0, wx.EXPAND|wx.ALL, 3)

        # Auto Start
        ############
        autostartsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Auto start torrents if')), wx.VERTICAL)        
        autoStartUploadBox = wx.BoxSizer(wx.HORIZONTAL)
        self.autostartUpload = wx.CheckBox(self, -1, _("Upload is more than"))
        autoStartUploadBox.Add(self.autostartUpload, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.autostartUploadThreshold = makeNumCtrl(self, 0, integerWidth = 4)
        autoStartUploadBox.Add(self.autostartUploadThreshold, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autoStartUploadBox.Add(wx.StaticText(self, wx.ID_STATIC, _("KB/s below global limit for")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.autostartUploadDelay = makeNumCtrl(self, 0, integerWidth = 4)
        autoStartUploadBox.Add(self.autostartUploadDelay, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autoStartUploadBox.Add(wx.StaticText(self, wx.ID_STATIC, _("seconds")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autostartsection.Add(autoStartUploadBox, 0, wx.ALL, 3)

        autoStartDownloadBox = wx.BoxSizer(wx.HORIZONTAL)
        self.autostartDownload = wx.CheckBox(self, -1, _("Download is less than"))
        autoStartDownloadBox.Add(self.autostartDownload, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.autostartDownloadThreshold = makeNumCtrl(self, 0, integerWidth = 4)
        autoStartDownloadBox.Add(self.autostartDownloadThreshold, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autoStartDownloadBox.Add(wx.StaticText(self, wx.ID_STATIC, _("KB/s for")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.autostartDownloadDelay = makeNumCtrl(self, 0, integerWidth = 4)
        autoStartDownloadBox.Add(self.autostartDownloadDelay, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autoStartDownloadBox.Add(wx.StaticText(self, wx.ID_STATIC, _("seconds")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autostartsection.Add(autoStartDownloadBox, 0, wx.ALL, 3)
        
        autoStartScrapeBox = wx.BoxSizer(wx.HORIZONTAL)
        self.autostartScrape = wx.CheckBox(self, -1, _("Torrent has less than"))
        autoStartScrapeBox.Add(self.autostartScrape, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.autostartScrapeValue = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.autostartScrapeValue.SetRange(1, 1000)
        autoStartScrapeBox.Add(self.autostartScrapeValue, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autoStartScrapeBox.Add(wx.StaticText(self, wx.ID_STATIC, _("seeds")), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        autostartsection.Add(autoStartScrapeBox, 0, wx.ALL, 3)

        # Default Behavior 
        ###################
        defaultbehaviorsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Default Behavior')), wx.VERTICAL)

        optionsTable = wx.FlexGridSizer(cols = 2, vgap = 3, hgap = 12)
        # Default priority for new torrents
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Default priority for new torrents:')), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.priorities = [ _('Highest'), 
                            _('High'), 
                            _('Normal'), 
                            _('Low'), 
                            _('Lowest') ]
        self.defaultpriority = wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), self.priorities)
        optionsTable.Add(self.defaultpriority, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 0) 

        # Default Status for new torrents
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Default status for new torrents:')), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        self.statuses = [_('Stop'), _('Queue')]
        self.defaultstatus = wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), self.statuses)
        optionsTable.Add(self.defaultstatus, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 0)

        defaultbehaviorsection.Add(optionsTable, 0, wx.EXPAND, 0)

        # Timeouts
        ###################
        timeoutsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Timeouts')), wx.VERTICAL)
        optionsTable = wx.FlexGridSizer(cols = 3, vgap = 3, hgap = 12)
                
        # Timeout for contacting tracker
        tracker_val  = ['oo', '5', '10', '15', '30', '45', '60', '120', '180'] #minute
        self.cb_tracker  = wx.ComboBox(self, -1, "", wx.Point(-1, -1), wx.Size(65, -1), tracker_val, style = wx.CB_READONLY | wx.CB_DROPDOWN)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Torrent can\'t connect for:')), 0, wx.ALIGN_CENTER_VERTICAL)
        optionsTable.Add(self.cb_tracker, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Minutes')), 0, wx.ALIGN_CENTER_VERTICAL)

        # Timeout for downloading
        download_val = ['oo', '10', '20', '30', '60', '90', '120', '150', '180', '210', '240'] #minute
        self.cb_download = wx.ComboBox(self, -1, "", wx.Point(-1, -1), wx.Size(65, -1), download_val, style = wx.CB_READONLY | wx.CB_DROPDOWN)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Torrent can\'t download for:')), 0, wx.ALIGN_CENTER_VERTICAL)
        optionsTable.Add(self.cb_download, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Minutes')), 0, wx.ALIGN_CENTER_VERTICAL)

        # Timeout for seeding
        upload_val   = ['oo', '0.5', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'] #hour
        self.cb_upload   = wx.ComboBox(self, -1, "", wx.Point(-1, -1), wx.Size(65, -1), upload_val, style = wx.CB_READONLY | wx.CB_DROPDOWN)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Seeding torrent doesn\'t upload for:')), 0, wx.ALIGN_CENTER_VERTICAL)
        optionsTable.Add(self.cb_upload, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, 5)
        optionsTable.Add(wx.StaticText(self, wx.ID_STATIC, _('Hours')), 0, wx.ALIGN_CENTER_VERTICAL)

        timeoutsection.Add(optionsTable, 0, wx.EXPAND, 0)

        ####################################################################
        sizer.Add(activitysection, 0, wx.EXPAND|wx.ALL, 3)
        sizer.Add(autostartsection, 0, wx.EXPAND|wx.ALL, 3)
        sizer.Add(defaultbehaviorsection, 0, wx.EXPAND|wx.ALL, 3)
        sizer.Add(timeoutsection, 0, wx.EXPAND|wx.ALL, 3)

        self.consideractive.Bind(wx.EVT_CHOICE, self.OnConsiderActive)        

        self.initTasks()       

    def OnConsiderActive(self, event):
        self.preferuncompleted.Enable(self.consideractive.GetSelection() == 2)
        event.Skip()
        
    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read
            
        currentprio = min(Read('defaultpriority', "int"), len(self.priorities) - 1)
        defaultprio = self.priorities[currentprio]
        self.defaultpriority.SetStringSelection(defaultprio)

        defaultstatus = self.statuses[Read('defaultstatus', "int")]
        self.defaultstatus.SetStringSelection(defaultstatus)

        consideractive = min(Read('consideractive', "int"), len(self.consideractiveOptions) - 1)
        self.consideractive.SetSelection(consideractive)

        self.preferuncompleted.Enable(consideractive==2)
        self.preferuncompleted.SetValue(Read('preferuncompleted', "boolean"))

        self.numsimtext.SetValue(Read('numsimdownload', "int"))
        
        self.cb_tracker.SetStringSelection(Read('timeouttracker'))
        self.cb_download.SetStringSelection(Read('timeoutdownload'))
        self.cb_upload.SetStringSelection(Read('timeoutupload'))

        self.autostartUpload.SetValue(Read('autostart_upload', "boolean"))
        self.autostartUploadThreshold.SetValue(Read('autostart_upload_threshold', "int"))
        self.autostartUploadDelay.SetValue(Read('autostart_upload_delay', "int"))
        
        self.autostartDownload.SetValue(Read('autostart_download', "boolean"))
        self.autostartDownloadThreshold.SetValue(Read('autostart_download_threshold', "int"))
        self.autostartDownloadDelay.SetValue(Read('autostart_download_delay', "int"))
        self.autostartScrape.SetValue(Read('autostart_scrape', "boolean"))
        self.autostartScrapeValue.SetValue(Read('autostart_scrape_value', "int"))
        

                
    def apply(self):            
        utility.config.Write('defaultpriority', self.defaultpriority.GetSelection())

        utility.config.Write('defaultstatus', self.defaultstatus.GetSelection())

        utility.config.Write('numsimdownload', self.numsimtext.GetValue())

        utility.config.Write('consideractive', self.consideractive.GetSelection())

        utility.config.Write('preferuncompleted', self.preferuncompleted.GetValue() and self.consideractive.GetSelection() == 2, "boolean")
        
        # Set values for timeouts
        utility.config.Write('timeouttracker', self.cb_tracker.GetValue())
        utility.config.Write('timeoutdownload', self.cb_download.GetValue())
        utility.config.Write('timeoutupload', self.cb_upload.GetValue())

        # Auto start
        utility.config.Write('autostart_upload', self.autostartUpload.GetValue(), "boolean")
        utility.config.Write('autostart_upload_threshold', self.autostartUploadThreshold.GetValue(), "int")
        utility.config.Write('autostart_upload_delay', self.autostartUploadDelay.GetValue(), "int")
        utility.config.Write('autostart_download', self.autostartDownload.GetValue(), "boolean")
        utility.config.Write('autostart_download_threshold', self.autostartDownloadThreshold.GetValue(), "int")
        utility.config.Write('autostart_download_delay', self.autostartDownloadDelay.GetValue(), "int")

        changed = False
        if utility.config.Write('autostart_scrape', self.autostartScrape.GetValue(), "boolean"):
            changed = True
        if utility.config.Write('autostart_scrape_value', self.autostartScrapeValue.GetValue(), "int"):
            changed = True
        if changed:
            [torrent.autoStartCheck() for torrent in utility.torrents["all"]]

        utility.queue.UpdateRunningTorrentCounters()
        
class BandwidthPanel(OptionPanel):
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)

        sizer = self.sizer
        
        # Upload Section
        ########################################
       
        uploadsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Upload Settings')), wx.VERTICAL)

        # Max uploads 
        maxuploadsbox = wx.BoxSizer(wx.HORIZONTAL)
        maxuploadsbox.Add(wx.StaticText(self, wx.ID_STATIC, _('Maximum uploads:')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.maxupload = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.maxupload.SetRange(2, 100)
        maxuploadsbox.Add(self.maxupload, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        uploadsection.Add(maxuploadsbox, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        # Upload limit when downloading
        maxoverall_up = wx.BoxSizer(wx.HORIZONTAL)
        maxoverall_up.Add(wx.StaticText(self, wx.ID_STATIC, _('Maximum overall upload rate when downloading:')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.uploadrate = makeNumCtrl(self, 0, integerWidth = 4)
        self.uploadrate.SetToolTipString(_('Amount of bandwidth to distribute between uploading torrents'))
        maxoverall_up.Add(self.uploadrate, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        maxoverall_up.Add(wx.StaticText(self, wx.ID_STATIC, _('KB/s')), 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 3)
        uploadsection.Add(maxoverall_up, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
        
        # Upload limit when not downloading
        maxoverall_seed_up = wx.BoxSizer(wx.HORIZONTAL)
        maxoverall_seed_up.Add(wx.StaticText(self, wx.ID_STATIC, _('Maximum overall upload rate when not downloading:')), 0, wx.ALIGN_CENTER_VERTICAL)
        self.seeduploadrate = makeNumCtrl(self, 0, integerWidth = 4)
        self.seeduploadrate.SetToolTipString(_('Amount of bandwidth to distribute between uploading torrents when not downloading'))
        maxoverall_seed_up.Add(self.seeduploadrate, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        maxoverall_seed_up.Add(wx.StaticText(self, wx.ID_STATIC, _('KB/s')), 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 3)
        uploadsection.Add(maxoverall_seed_up, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)       

        uploadsection.Add(wx.StaticText(self, wx.ID_STATIC, _('0 = No limit')), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5)
        sizer.Add(uploadsection, 0, wx.EXPAND|wx.ALL, 5)

        # Download Section
        ########################################
        downloadsection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Download Settings')), wx.VERTICAL)

        self.downloadrate = makeNumCtrl(self, 0, integerWidth = 4)

        maxdownoverall_down = wx.BoxSizer(wx.HORIZONTAL)
        maxdownoverall_down.Add(wx.StaticText(self, wx.ID_STATIC, _('Maximum overall download rate:')), 0, wx.ALIGN_CENTER_VERTICAL)
        maxdownoverall_down.Add(self.downloadrate, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        maxdownoverall_down.Add(wx.StaticText(self, wx.ID_STATIC, _('KB/s')), 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 3)
        
        downloadsection.Add(maxdownoverall_down, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        downloadsection.Add(wx.StaticText(self, wx.ID_STATIC, _('0 = No limit')), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5)        

        sizer.Add(downloadsection, 0, wx.EXPAND|wx.ALL, 5)

        # Upload setting for completed files
        ########################################

        continuesection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Seeding options')), wx.VERTICAL)

        # Time
        timesizer = wx.BoxSizer(wx.HORIZONTAL)
        timesizer.Add(wx.StaticText(self, -1, _('Continue upload for:')), 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)       
        self.cbtime = DHMTimeCtrl(self)
        timesizer.Add(self.cbtime, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        timesizer.Add(self.cbtime.GetSpinButton(), 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 2)
        continuesection.Add(timesizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.LEFT, 5)
       
        # Ratio
        ratiosizer = wx.BoxSizer(wx.HORIZONTAL)
        ratiosizer.Add(wx.StaticText(self, -1, _('Or until ratio reaches:')), 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
        ratioval = ['0', '50', '60', '70', '75', '80', '90', '100', '125', '150', '175', '200', '300', '400', '500']
        self.cbratio = wx.ComboBox(self, -1, "", wx.Point(-1, -1), wx.Size(65, -1), ratioval, wx.CB_DROPDOWN|wx.CB_READONLY)
        ratiosizer.Add(self.cbratio, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        ratiosizer.Add(wx.StaticText(self, -1, "%"), 0, wx.ALIGN_CENTER_VERTICAL | wx.LEFT, 5)
        continuesection.Add(ratiosizer, 0, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.LEFT | wx.UP, 5)

        continuesection.Add(wx.StaticText(self, wx.ID_STATIC, _('0 = Ignore')), 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5)        

        sizer.Add(continuesection, 0, wx.EXPAND|wx.ALL, 5)
        
        # Prioritize Local
        ########################################
        self.prioritizelocal = wx.CheckBox(self, -1, _('Don\'t count torrents with local settings towards global limit'))
        sizer.Add(self.prioritizelocal, 0, wx.ALL, 5)
    
        self.initTasks()

    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read
        self.maxupload.SetValue(Read('maxupload', "int"))
        self.uploadrate.SetValue(Read('maxuploadrate', "int"))
        self.downloadrate.SetValue(Read('maxdownloadrate', "int"))
        self.seeduploadrate.SetValue(Read('maxseeduploadrate', "int"))
        self.prioritizelocal.SetValue(Read('prioritizelocal', "boolean"))
        
        self.cbtime.SetValue(Read('uploadtime', "int"))
        self.cbratio.SetValue(Read('uploadratio'))
        
    def apply(self):
        # Check max upload rate input must be integer
        ##############################################
        upload_rate     = int(self.uploadrate.GetValue())
        seedupload_rate = int(self.seeduploadrate.GetValue())
        
        download_rate = int(self.downloadrate.GetValue())

        # Check max upload rate must not be less than 3 kB/s
        ######################################################
        if (upload_rate < 3 and upload_rate != 0) or (seedupload_rate < 3 and seedupload_rate != 0):
            #display warning
            dlg = wx.MessageDialog(self, _('Upload rate must be at least 3 KB/s'), _('Error'), wx.ICON_ERROR)
            dlg.ShowModal()
            dlg.Destroy()
            return False

        utility.config.Write('prioritizelocal', self.prioritizelocal.GetValue(), "boolean")

        # Set new value to parameters
        ##############################
        utility.config.Write('maxuploadrate', upload_rate)
        utility.config.Write('maxseeduploadrate', seedupload_rate)
        
        utility.config.Write('maxdownloadrate', download_rate)
        

        cbtime = self.cbtime.GetValue(asInt = True)
        if 0 != cbtime < 1800:
            cbtime = 1800


        changed = False
        if utility.config.Write('uploadtime', cbtime, "int"):
            changed = True
        if utility.config.Write('uploadratio', self.cbratio.GetValue()):
            changed = True
        if utility.config.Write('maxupload', self.maxupload.GetValue()):
            changed = True
        if changed:
            utility.window.details.settingPage.defaultChanged()
        
class BitTorrentPanel(OptionPanel):
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)

        sizer = self.sizer
        
        # Security
        ########################################
        securitysection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Security')), wx.VERTICAL)

        # encryption
        self.crypto_mode_options = [_('Disabled'),
                                    _('Enabled'),
                                    _('Forced'),
                                    _('Stealth')]
        self.crypto_mode  = wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), self.crypto_mode_options)
        crypto_box = wx.BoxSizer(wx.HORIZONTAL)
        crypto_box.Add(wx.StaticText(self, wx.ID_STATIC, _('Encryption: ')), 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        crypto_box.Add(self.crypto_mode, 0, wx.ALIGN_CENTER_VERTICAL)
        securitysection.Add(crypto_box, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # kick/ban
        self.kickban = wx.CheckBox(self, -1, _('Kick/Ban clients that send you bad data'))
        securitysection.Add(self.kickban, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # not same ip
        self.notsameip = wx.CheckBox(self, -1, _('Don\'t allow multiple connections from the same IP'))
        securitysection.Add(self.notsameip, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        self.ipfilter = wx.CheckBox(self, -1, _('Enable IP filtering'))
        securitysection.Add(self.ipfilter, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        
        sizer.Add(securitysection, 0, wx.EXPAND|wx.ALL, 5)
        
        # BitTorrent Extensions
        ########################################
        extensionssection = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('BitTorrent Extensions')), wx.VERTICAL)

        # pex
        self.enablepex = wx.CheckBox(self, -1, _('Peer Exchange'))
        extensionssection.Add(self.enablepex, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # dht
        self.enabledht = wx.CheckBox(self, -1, _('DHT (requires restart)'))
        extensionssection.Add(self.enabledht, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        # do or don't get scrape data
        self.scrape = wx.CheckBox(self, -1, _('Retrieve scrape data'))
        self.scrape.SetToolTipString(_('Automatically retrieve the total number of seeds/peers'))
        extensionssection.Add(self.scrape, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        self.scrape.Bind(wx.EVT_CHECKBOX, self.onScrapeClicked)

        # scrape or don't queued torrents
        self.scrapequeued = wx.CheckBox(self, -1, _('Also scrape queued torrents'))
        self.scrapequeued.SetToolTipString(_('Automatically retrieve the total number of seeds/peers for queued torrents'))
        extensionssection.Add(self.scrapequeued, 0, wx.ALIGN_LEFT|wx.ALL, 5)

        sizer.Add(extensionssection, 0, wx.EXPAND|wx.ALL, 5)
    
        self.initTasks()
            
    def onScrapeClicked(self, event):
        self.scrapequeued.Enable(event.IsChecked())
        event.Skip()
            
    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read

        crypto_mode_opt = Read('crypto_mode', "int")
        if crypto_mode_opt >= len(self.crypto_mode_options):
            crypto_mode_opt = 1
        crypto_mode = self.crypto_mode_options[crypto_mode_opt]
        self.crypto_mode.SetStringSelection(crypto_mode)
        
        self.enablepex.SetValue(Read('pex_allowed', "boolean"))
        self.enabledht.SetValue(Read('dht', "boolean"))
        self.kickban.SetValue(Read('kickban', "boolean"))
        self.notsameip.SetValue(Read('notsameip', "boolean"))
        self.ipfilter.SetValue(Read('ipfilter', "boolean"))
        self.scrape.SetValue(Read('scrape', "boolean"))
        self.scrapequeued.SetValue(Read('scrapequeued', "boolean"))
        self.scrapequeued.SetValue(Read('scrapequeued', "boolean"))
        self.scrapequeued.Enable(self.scrape.GetValue())       
        
    def apply(self):
        utility.config.Write('crypto_mode', self.crypto_mode.GetSelection())
        utility.config.Write('pex_allowed', self.enablepex.GetValue(), "boolean")
        utility.config.Write('dht', self.enabledht.GetValue(), "boolean")
        utility.config.Write('kickban', self.kickban.GetValue(), "boolean")
        utility.config.Write('notsameip', self.notsameip.GetValue(), "boolean")
        utility.ipfilter.enable(self.ipfilter.GetValue())
        
        if self.scrape.GetValue():
            utility.config.Write('scrape', "1")
            utility.config.Write('scrapequeued', self.scrapequeued.GetValue(), "boolean")
        else:
            utility.config.Write('scrape', "0")
            utility.config.Write('scrapequeued', "0")
                        
#######################################################################################
class DiskPanel(OptionPanel):
    def __init__(self, parent):
        OptionPanel.__init__(self, parent)
        
        sizer = self.sizer
    
        diskbox = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Disk Settings')), wx.VERTICAL)

        diskdatasizer = wx.FlexGridSizer(cols = 3, vgap = 3, hgap = 12)
        diskdatasizer.AddGrowableCol(1)        
       
        # Torrent Directory Scanner
        self.scannercheckbox = wx.CheckBox(self, -1, _('Auto load torrents from'))
        self.scannercheckbox.SetToolTipString(_("Automatically load torrents from a specified directory.\nWARNING: Don't set this to the torrent dir in %APPDATA%"))
        self.scannerdir = wx.TextCtrl(self, -1, "")
        scannerbrowsebtn = wx.Button(self, -1, "...", style = wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onBrowseScanDir, scannerbrowsebtn)

        diskdatasizer.Add(self.scannercheckbox, 0, wx.ALIGN_CENTER_VERTICAL, 0) 
        diskdatasizer.Add(self.scannerdir, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
        diskdatasizer.Add(scannerbrowsebtn, 0, wx.ALIGN_CENTER_VERTICAL, 0)

        # Default folder
        self.defaultdir = wx.CheckBox(self, -1, _('Default download folder'))
        self.dir = wx.TextCtrl(self, -1, "")
        browsebtn = wx.Button(self, -1, "...", style = wx.BU_EXACTFIT)
        self.Bind(wx.EVT_BUTTON, self.onBrowseDir, browsebtn)
        
        diskdatasizer.Add(self.defaultdir, 0, wx.ALIGN_CENTER_VERTICAL, 0) 
        diskdatasizer.Add(self.dir, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
        diskdatasizer.Add(browsebtn, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        
        # Move completed
        self.movecompleted = wx.CheckBox(self, -1, _('Move completed files to'))
        self.movedir = wx.TextCtrl(self, -1, "")
        movebrowsebtn = wx.Button(self, -1, "...", style = wx.BU_EXACTFIT)
        self.Bind(wx.EVT_CHECKBOX, self.onMoveCompletedChanged, self.movecompleted)
        self.Bind(wx.EVT_BUTTON, self.onBrowseMoveDir, movebrowsebtn)
        self.movecompletedonclear = wx.CheckBox(self, -1, _('Only move on `Clear Completed`'))
        self.addlabeltomovedir = wx.CheckBox(self, -1, _('Add label to move dir'))

        diskdatasizer.Add(self.movecompleted, 0, wx.ALIGN_CENTER_VERTICAL, 0) 
        diskdatasizer.Add(self.movedir, 0, wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 0)
        diskdatasizer.Add(movebrowsebtn, 0, wx.ALIGN_CENTER_VERTICAL, 0)
        diskdatasizer.Add(self.movecompletedonclear, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 10)
        diskdatasizer.Add(self.addlabeltomovedir, 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 10)
        diskdatasizer.Add((0,-1), 0, wx.ALIGN_CENTER_VERTICAL, 0)

        diskbox.Add(diskdatasizer, 1, wx.EXPAND|wx.ALL, 3)
        
        # Disk Full check
        diskfullbox = wx.BoxSizer(wx.HORIZONTAL)
        self.diskfullcheckbox = wx.CheckBox(self, -1, _('Stop torrent if destination has less than'))
        self.diskfullthreshold = makeNumCtrl(self, 10, integerWidth = 4)
        diskfullbox.Add(self.diskfullcheckbox, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        diskfullbox.Add(self.diskfullthreshold, 0, wx.ALIGN_CENTER_VERTICAL|wx.RIGHT, 5)
        diskfullbox.Add(wx.StaticText(self, wx.ID_STATIC, _('MB')), 0, wx.ALIGN_CENTER_VERTICAL)
        diskbox.Add(diskfullbox, 0, wx.ALIGN_LEFT|wx.ALL, 3)
        
        # Advanced Disk Settings
        advancedbox = wx.StaticBoxSizer(wx.StaticBox(self, -1, _('Advanced Disk Settings')), wx.VERTICAL)

        advdatasizer = wx.FlexGridSizer(cols = 2, vgap = 3, hgap = 12)

        # Allocation Type
        alloc_choices = [_('Normal'), 
                         _('Background'), 
                         _('Pre-Allocate'), 
                         _('Sparse')]
        self.alloc_strings = {"normal": 0, "background": 1, "pre-allocate": 2, "sparse": 3}
        self.alloctype_data=wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), alloc_choices)
        advdatasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Disk allocation type:')), 1, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 0)
        advdatasizer.Add(self.alloctype_data, 0, wx.EXPAND, 0)

        # Allocation Rate
        self.allocrate_data = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.allocrate_data.SetRange(1, 100)
        advdatasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Allocation rate:')), 1, wx.ALIGN_CENTER_VERTICAL)
        allocrate_box = wx.BoxSizer(wx.HORIZONTAL)
        allocrate_box.Add(self.allocrate_data)
        allocrate_box.Add(wx.StaticText(self, wx.ID_STATIC, _('MB/s')), 1, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        advdatasizer.Add(allocrate_box, 0, wx.EXPAND, 0)

        # Locking Method
        locking_choices = [_('No locking'), 
                           _('Lock while writing'), 
                           _('Lock always')]
        self.locking_data=wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), locking_choices)
        advdatasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('File locking:')), 1, wx.ALIGN_CENTER_VERTICAL)
        advdatasizer.Add(self.locking_data, 0, wx.EXPAND, 0)

        # Doublecheck Method
        doublecheck_choices = [_('No extra checking'), 
                               _('Double-check'), 
                               _('Triple-check')]
        self.doublecheck_data=wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), doublecheck_choices)
        advdatasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Extra data checking:')), 1, wx.ALIGN_CENTER_VERTICAL)
        advdatasizer.Add(self.doublecheck_data, 0, wx.EXPAND, 0)

        # Maximum Files Open
        self.maxfilesopen_choices = ['50', '100', '200', _('No Limit')]
        self.maxfilesopen_data=wx.Choice(self, -1, wx.Point(-1, -1), wx.Size(-1, -1), self.maxfilesopen_choices)
        advdatasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Max files open:')), 1, wx.ALIGN_CENTER_VERTICAL)
        advdatasizer.Add(self.maxfilesopen_data, 0, wx.EXPAND, 0)        

        # Expire cache data
        self.expirecache_choices = [_('Never'), '3', '5', '7', '10', '15', '30', '60', '90']
        self.expirecache_data = wx.Choice(self, -1, choices = self.expirecache_choices)
        advdatasizer.Add(wx.StaticText(self, wx.ID_STATIC, _('Expire resume data(days):')), 1, wx.ALIGN_CENTER_VERTICAL)
        advdatasizer.Add(self.expirecache_data, 0, wx.EXPAND, 0)        

        # Flush data        
        self.flush_data_enable = wx.CheckBox(self, -1, _('Flush data to disk every'))
        self.flush_data = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.flush_data.SetRange(0, 999)
        advdatasizer.Add(self.flush_data_enable, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 0)
        flush_box = wx.BoxSizer(wx.HORIZONTAL)
        flush_box.Add(self.flush_data, 0, wx.ALIGN_CENTER_VERTICAL)
        flush_box.Add(wx.StaticText(self, wx.ID_STATIC, _('Minutes')), 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        advdatasizer.Add(flush_box, 0, wx.EXPAND, 0)

        
        # Disk buffering
        self.buffer_read_enable = wx.CheckBox(self, -1, _('Buffering Read Cache'))    
        advdatasizer.Add(self.buffer_read_enable, 0, wx.EXPAND, 5)
        advdatasizer.Add((-1, -1))

        self.buffer_write_enable = wx.CheckBox(self, -1, _('Buffering Write Cache'))
        self.buffer_write = wx.SpinCtrl(self, size = wx.Size(60, -1))
        self.buffer_write.SetRange(0, 999)
        advdatasizer.Add(self.buffer_write_enable, 0, wx.ALIGN_CENTER_VERTICAL|wx.EXPAND, 5)
        buffer_write_box = wx.BoxSizer(wx.HORIZONTAL)
        buffer_write_box.Add(self.buffer_write, 0, wx.ALIGN_CENTER_VERTICAL)
        buffer_write_box.Add(wx.StaticText(self, wx.ID_STATIC, _('MB')), 0, wx.ALIGN_CENTER_VERTICAL|wx.LEFT, 5)
        advdatasizer.Add(buffer_write_box, 0, wx.EXPAND, 0)

        advancedbox.Add(advdatasizer, 0, wx.ALL, 3)

        # Put it all together ;)
        sizer.Add(diskbox, 0, wx.EXPAND|wx.ALL, 3)
        sizer.Add(advancedbox, 0, wx.EXPAND|wx.ALL, 3)

        self.initTasks()

        self.onMoveCompletedChanged()

    def loadValues(self, Read = None):
        if Read is None:
            Read = utility.config.Read

        self.dir.SetValue(Read('defaultfolder'))
        self.defaultdir.SetValue(Read('setdefaultfolder', "boolean"))

        self.movecompleted.SetValue(Read('movecompleted', "boolean"))
        self.movedir.SetValue(Read('defaultmovedir'))
        self.movecompletedonclear.SetValue(Read('movecompletedonclear', "boolean"))
        self.addlabeltomovedir.SetValue(Read('addlabeltomovedir', "boolean"))

        self.scannercheckbox.SetValue(Read('scandiractive', "boolean"))
        self.scannerdir.SetValue(Read('scandir'))
        
        diskfullthreshold = Read('diskfullthreshold', "int")
        if diskfullthreshold > 0:
            self.diskfullcheckbox.SetValue(True)
            self.diskfullthreshold.SetValue(diskfullthreshold)

        # Advanced
        try:
            alloc_selection = self.alloc_strings[Read('alloc_type')]
        except:
            alloc_selection = 0
        self.alloctype_data.SetSelection(alloc_selection)
        
        self.allocrate_data.SetValue(Read('alloc_rate', "int"))
        
        if Read('lock_files', "int"):
            if Read('lock_while_reading', "int"):
                self.locking_data.SetSelection(2)
            else:
                self.locking_data.SetSelection(1)
        else:
            self.locking_data.SetSelection(0)
        
        if Read('double_check', "int"):
            if Read('triple_check', "int"):
                self.doublecheck_data.SetSelection(2)
            else:
                self.doublecheck_data.SetSelection(1)
        else:
            self.doublecheck_data.SetSelection(0)
        
        setval = Read('max_files_open', "int")
        if setval == 0:
            setval = _('No Limit')
        else:
            setval = str(setval)
        if not setval in self.maxfilesopen_choices:
            setval = self.maxfilesopen_choices[0]
        self.maxfilesopen_data.SetStringSelection(setval)
        
        self.buffer_read_enable.SetValue(Read('buffer_read', "boolean"))
        
        try:
            flushval = Read('auto_flush', "int")
        except:
            flushval = 0
        self.flush_data.SetValue(flushval)
        self.flush_data_enable.SetValue(flushval > 0)
        
        try:
            writeval = Read('buffer_write', "int")
        except:
            writeval = 0
        self.buffer_write.SetValue(writeval)
        self.buffer_write_enable.SetValue(writeval > 0)

        setval = Read('expire_cache_data', "int")
        if setval == 0:
            setval = _('Never')
        else:
            setval = str(setval)
        if not setval in self.expirecache_choices:
            setval = self.expirecache_choices[0]
        self.expirecache_data.SetStringSelection(setval)

    def apply(self):
        utility.config.Write('setdefaultfolder', self.defaultdir.GetValue(), "boolean")
        utility.config.Write('defaultfolder', self.dir.GetValue())

        utility.config.Write('movecompleted', self.movecompleted.GetValue(), "boolean")
        utility.config.Write('defaultmovedir', self.movedir.GetValue())
        utility.config.Write('movecompletedonclear', self.movecompletedonclear.GetValue(), "boolean")
        utility.config.Write('addlabeltomovedir', self.addlabeltomovedir.GetValue(), "boolean")

        if not self.scannerdir.GetValue() or not self.defaultdir.GetValue():
            self.scannercheckbox.SetValue(False)
        utility.config.Write('scandiractive', self.scannercheckbox.GetValue(), "boolean")
        utility.config.Write('scandir', self.scannerdir.GetValue())
        
        if self.diskfullcheckbox.GetValue():
            diskfullthreshold = self.diskfullthreshold.GetValue()
        else:
            diskfullthreshold = 0
        utility.config.Write('diskfullthreshold', diskfullthreshold, "int")

        # Advanced
        alloc_strings = ["normal", "background", "pre-allocate", "sparse"]
        
        utility.config.Write('alloc_type', alloc_strings[self.alloctype_data.GetSelection()])
        utility.config.Write('alloc_rate', int(self.allocrate_data.GetValue()), "int")

        try:
            maxopen = int(self.maxfilesopen_data.GetStringSelection())
        except:       # if it ain't a number, it must be "no limit"
            maxopen = 0
        utility.config.Write('max_files_open', maxopen, "int")

        try:
            expirecache = int(self.expirecache_data.GetStringSelection())
        except:       # if it ain't a number, it must be "never"
            expirecache = 0
        utility.config.Write('expire_cache_data', expirecache, "int")

        utility.config.Write('lock_files', self.locking_data.GetSelection() >= 1, "boolean")
        utility.config.Write('lock_while_reading', self.locking_data.GetSelection() > 1, "boolean")

        utility.config.Write('double_check', self.doublecheck_data.GetSelection() >= 1, "boolean")
        utility.config.Write('triple_check', self.doublecheck_data.GetSelection() > 1, "boolean")
        
        utility.config.Write('buffer_read', self.buffer_read_enable.GetValue(), "boolean")
        
        if not self.buffer_write_enable.GetValue():
            writeval = 0
        else:
            writeval = self.buffer_write.GetValue()
        utility.config.Write('buffer_write', writeval)
        
        if not self.flush_data_enable.GetValue():
            flushval = 0
        else:
            flushval = self.flush_data.GetValue()
        utility.config.Write('auto_flush', flushval)

    def onBrowseMoveDir(self, event = None):
        dlg = wx.DirDialog(self, 
                           _('choose move folder'), 
                           style = wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
        if dlg.ShowModal() == wx.ID_OK:
            self.movedir.SetValue(dlg.GetPath())
        dlg.Destroy()
        
    def onBrowseScanDir(self, event = None):
        dlg = wx.DirDialog(self, 
                           _('choose scan folder'), 
                           style = wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
        if dlg.ShowModal() == wx.ID_OK:
            self.scannerdir.SetValue(dlg.GetPath())
        dlg.Destroy()

    def onBrowseDir(self, event = None):
        dlg = wx.DirDialog(self, 
                           _('choose default download folder'), 
                           style = wx.DD_DEFAULT_STYLE | wx.DD_NEW_DIR_BUTTON)
        if dlg.ShowModal() == wx.ID_OK:
            self.dir.SetValue(dlg.GetPath())
        dlg.Destroy()

    def onMoveCompletedChanged(self, event = None):
        enabled = self.movecompleted.GetValue()
        self.movecompletedonclear.Enable(enabled)
        self.addlabeltomovedir.Enable(enabled)
        
